//
// Created by suhuamo on 25-7-16.
//

#include<iostream>
#include<WS2tcpip.h>

using namespace std;

/**
 *
 * ffmpeg 命令行生成 flv 文件:
 * ffmpeg -i input.mp4 input.flv
 *
 * 测试:
 * 1. 使用ffplay测试，命令如下：
 *      ffplay http://127.0.0.1:8080/index.flv
 * 2. 使用 httpFlvPlay.html 测试
 *  注意，如果播放失败，可能是编码问题，目前 httpFlvPlay.html 播放不支持h265编码, 可以使用 ffmpeg 命令转换编码格式：
 *           ffmpeg -i .\input.mp4 -c:v libx264 -c:a copy input.flv
 *
 *  httpFlv讲解：
 *  这个协议更加简单，保持http长链接，一直发送文件原始数据就行了。
 *  正常来说一次http请求发送完成就结束了，由于文件太大，故并不是一次http发送完毕，而是建立了http连接，一直持续不断的发送文件数据，
 *  就和ws一模一样了其实。
 *  需要注意的是 Content-Type ，指定了本次是 httpFlv 请求
 */

void doClient(int clientFd);

int main() {
    int port = 8080;
    printf("httpFlvServer http://127.0.0.1:%d/input.flv\n", port);

    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        printf("wsaStartup fail");
        return -1;
    }
    
    int serverFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    SOCKADDR_IN serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    serverAddr.sin_port = htons(port);
    if (bind(serverFd, (sockaddr*)&serverAddr, sizeof(sockaddr)) != 0) {
        printf("bind error");
        return -1;
    }

    if (listen(serverFd, SOMAXCONN) < 0) {
        printf("listen error");
        return -1;
    }

    while (true) {
        printf("wait connection...\n");
        sockaddr_in clientAddr;
        int len = sizeof(sockaddr);
        int clientFd = accept(serverFd, (sockaddr*)&clientAddr, &len);
        if (clientFd == SOCKET_ERROR) {
            printf("accept error\n");
            break;
        }
        printf("new connect = %d\n", clientFd);
        doClient(clientFd);
    }

    closesocket(serverFd);
    return 0;
}

void doClient(int clientFd) {
    std::string filename = "D:\\code\\CLion\\study\\media_stream\\data\\input.flv";
    FILE *fp = fopen(filename.data(), "rb");
    if (!fp) {
        printf("fopen %s error\n", filename.data());
        return;
    }

    const char http_headers[] = \
        "HTTP/1.1 200 OK\r\n" \
        "Access-Control-Allow-Origin: * \r\n" \
        "Content-Type: video/x-flv\r\n" \
        "Connection: Keep-Alive\r\n" \
        "Expires: -1\r\n" \
        "Pragma: no-cache\r\n" \
        "\r\n"
        ;
    // "Content-Length: -1\r\n"
    int http_headers_len = strlen(http_headers);

    char bufRecv[2000] = {0};
    int bufRecvSize = recv(clientFd, bufRecv, 2000, 0);
    printf("bufRecvSize=%d bufRecv=%s\n", bufRecvSize, bufRecv);

    // 第一次发送是发送请求头
    send(clientFd, http_headers, http_headers_len, 0);

    // 接下来每次发送的都是音视频原始数据
    char buf[5000] = {0};
    while (true) {
        int bufLen = fread(buf, 1, sizeof(buf), fp);
        int ret = send(clientFd, buf, bufLen, 0);
        if (ret <= 0) {
            break;
        }
    }

    if (fp) {
        fclose(fp);
    }
    closesocket(clientFd);
    return;
}